/*
 * Copyright 2006 Mark Bakker <mark.bakker AT gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.gwtsvg.client;

import com.google.gwt.user.client.Element;

/**
 *
 */
public abstract class BasicShape extends SVGWidget {

  protected BasicShape(Element elem) {
    super(elem);
  }

  /**
   * <p>
   * The <strong>'fill'</strong> property paints the interior of the given
   * graphical element. The area to be painted consists of any areas inside the
   * outline of the shape. To determine the inside of the shape, all subpaths
   * are considered, and the interior is determined according to the rules
   * associated with the current value of the <strong>'fill-rule'</strong>
   * property. The zero-width geometric outline of a shape is included in the
   * area to be painted.
   * </p>
   *
   * <p>
   * The fill operation fills open subpaths by performing the fill operation as
   * if an additional "closepath" command were added to the path to connect the
   * last point of the subpath with the first point of the subpath. Thus, fill
   * operations apply to both open subpaths within 'path' elements (i.e.,
   * subpaths without a closepath command) and 'polyline' elements.
   * </p>
   *
   * @param color the filling color
   */
  public void setFill(Color color) {
    setAttributeNS(getElement(), "fill", color.getHexValue());
  }

  /**
   * <p>
   * <strong>'fill-opacity'</strong> specifies the opacity of the painting
   * operation used to paint the interior the current object.
   * </p>
   *
   * @param fillOpacity The opacity of the painting operation used to fill the
   *          current object. Any values outside the range 0.0 (fully
   *          transparent) to 1.0 (fully opaque) will be clamped to this range.
   */
  public void setFillOpacity(double fillOpacity) {
    setAttributeNS(getElement(), "fill-opacity", "" + fillOpacity);
  }

  /**
   * <p>
   * The <strong>'fill-rule'</strong> property indicates the algorithm which is
   * to be used to determine what parts of the canvas are included inside the
   * shape. For a simple, non-intersecting path, it is intuitively clear what
   * region lies "inside"; however, for a more complex path, such as a path that
   * intersects itself or where one subpath encloses another, the interpretation
   * of "inside" is not so obvious.
   * </p>
   *
   * <p>
   * The <strong>'fill-rule'</strong> property provides two options for how the
   * inside of a shape is determined:
   * </p>
   *
   * <p>
   * <strong>nonzero</strong>
   * </p>
   * <p>
   * This rule determines the "insideness" of a point on the canvas by drawing a
   * ray from that point to infinity in any direction and then examining the
   * places where a segment of the shape crosses the ray. Starting with a count
   * of zero, add one each time a path segment crosses the ray from left to
   * right and subtract one each time a path segment crosses the ray from right
   * to left. After counting the crossings, if the result is zero then the point
   * is outside the path. Otherwise, it is inside. The following drawing
   * illustrates the <strong>nonzero</strong> rule:
   * </p>
   * <p>
   * <img class='gallery'
   * src='http://www.w3.org/TR/SVG11/images/painting/fillrule-nonzero.png'/>
   * </p>
   *
   * <p>
   * <strong>evenodd</strong>
   * </p>
   * <p>
   * This rule determines the "insideness" of a point on the canvas by drawing a
   * ray from that point to infinity in any direction and counting the number of
   * path segments from the given shape that the ray crosses. If this number is
   * odd, the point is inside; if even, the point is outside. The following
   * drawing illustrates the <strong>evenodd</strong> rule:
   * </p>
   * <p>
   * <img class='gallery'
   * src='http://www.w3.org/TR/SVG11/images/painting/fillrule-evenodd.png'/>
   * </p>
   *
   * <p>
   * (Note: the above explanations do not specify what to do if a path segment
   * coincides with or is tangent to the ray. Since any ray will do, one may
   * simply choose a different ray that does not have such problem
   * intersections.)
   * </p>
   *
   * @param fillRule the <strong>'fill-rule'</strong> to be set
   */
  public void setFillRule(FillRule fillRule) {
    setAttributeNS(getElement(), "fill-rule", fillRule.getFillRule());
  }

  /**
   * Sets the stroke and fill opacity. Values outside of the valid range are
   * ignored.
   *
   * @param opacity percent value between 0 - 1
   */
  public void setOpacity(double opacity) {
    setAttributeNS(getElement(), "opacity", "" + opacity);
  }

  /**
   * The <strong>'stroke'</strong> property paints along the outline of the
   * given graphical element.
   *
   * @param color the stroke color
   */
  public void setStroke(Color color) {
    setAttributeNS(getElement(), "stroke", color.getHexValue());
  }

  /**
   * <p>
   * <strong>'stroke-dasharray'</strong> controls the pattern of dashes and
   * gaps used to stroke paths. <code>dashes</code> contains a list of
   * comma-separated (with optional white space) <length>s that specify the
   * lengths of alternating dashes and gaps. If an odd number of values is
   * provided, then the list of values is repeated to yield an even number of
   * values. Thus, <strong>stroke-dasharray: 5,3,2</strong> is equivalent to
   * <strong>stroke-dasharray: 5,3,2,5,3,2</strong>.
   * </p>
   *
   * @param dashes A list of comma-separated <length>'s (with optional white
   *          space). If the sum of the <length>'s is zero, then the stroke is
   *          rendered as if a value of none were specified.
   */
  public void setStrokeDash(double[] dashes) {
    String dash = null;
    for (int i = 0; i < dashes.length; i++) {
      double dashValue = dashes[i];
      dash = dash + dashValue;
      if ((i + 1) < dashes.length) {
        dash = dash + ",";
      }
    }
    setAttributeNS(getElement(), "stroke-dasharray", dash);
  }

  /**
   * <p>
   * <strong>'stroke-dasharray'</strong> controls the pattern of dashes and
   * gaps used to stroke paths. <code>dash</code> specify the lengths of
   * alternating dashes and gaps.
   *
   * @param dash If the dash <length>'s is zero, then the stroke is rendered as
   *          if a value of none were specified.
   */
  public void setStrokeDash(double dash) {
    setAttributeNS(getElement(), "stroke-dasharray", "" + dash);
  }

  /**
   * <p>
   * <strong>'stroke-dashoffset'</strong> specifies the distance into the dash
   * pattern to start the dash.
   * </p>
   *
   *
   * @param dashOffset specify the length where the dash will start
   */
  public void setStrokeDashOffset(double dashOffset) {
    setAttributeNS(getElement(), "stroke-dashoffset", "" + dashOffset);
  }

  /**
   * <p>
   * <strong>'stroke-linecap'</strong> specifies the shape to be used at the
   * end of open subpaths when they are stroked.
   * </p>
   *
   * </p>
   * <strong>butt</strong>
   * </p>
   * See drawing below.
   * <p>
   * <img class='gallery'
   * src='http://www.w3.org/TR/SVG11/images/painting/linecap.png'/>
   * </p>
   *
   * @param linecap value may be butt, round, square
   */
  public void setStrokeLinecapBut() {
    setAttributeNS(getElement(), "stroke-linecap", "butt");
  }

  /**
   * <p>
   * <strong>'stroke-linecap'</strong> specifies the shape to be used at the
   * end of open subpaths when they are stroked.
   * </p>
   *
   * </p>
   * <strong>round</strong>
   * </p>
   * See drawing below.
   * <p>
   * <img class='gallery'
   * src='http://www.w3.org/TR/SVG11/images/painting/linecap.png'/>
   * </p>
   *
   * @param linecap value may be butt, round, square
   */
  public void setStrokeLinecapRound() {
    setAttributeNS(getElement(), "stroke-linecap", "round");
  }

  /**
   * <p>
   * <strong>'stroke-linecap'</strong> specifies the shape to be used at the
   * end of open subpaths when they are stroked.
   * </p>
   *
   * </p>
   * <strong>square</strong>
   * </p>
   * See drawing below.
   * <p>
   * <img class='gallery'
   * src='http://www.w3.org/TR/SVG11/images/painting/linecap.png'/>
   * </p>
   */
  public void setStrokeLinecapSquare() {
    setAttributeNS(getElement(), "stroke-linecap", "square");
  }

  /**
   * <p>
   * <strong>'stroke-linejoin'</strong> specifies the shape to be used at the
   * corners of paths or basic shapes when they are stroked.
   * </p>
   *
   * </p>
   * <strong>miter</strong>
   * </p>
   * See drawing below.
   * </p>
   * <strong>round</strong>
   * </p>
   * See drawing below.
   * </p>
   * <strong>bevel</strong>
   * </p>
   * See drawing below.
   * <p>
   * <img class='gallery'
   * src='http://www.w3.org/TR/SVG11/images/painting/linejoin.png'/>
   * </p>
   *
   * @param linecap value may be butt, round, square
   */
  public void setStrokeLinejoin(String linejoin) {
    setAttributeNS(getElement(), "stroke-linejoin", linejoin);
  }

  /**
   * <p>
   * <strong>'stroke-opacity'</strong> specifies the opacity of the painting
   * operation used to stroke the current object.
   * </p>
   *
   * @param fillOpacity The opacity of the painting operation used to stroke the
   *          current object. Any values outside the range 0.0 (fully
   *          transparent) to 1.0 (fully opaque) will be clamped to this range.
   */
  public void setStrokeOpacity(double strokeOpacity) {
    setAttributeNS(getElement(), "stroke-opacity", "" + strokeOpacity);
  }

  /**
   * The width of the stroke on the current object. If a percentage is used, the
   * value represents a percentage of the current viewport. (See Units.) A zero
   * value causes no stroke to be painted
   *
   * @param width the width of the stroke
   */
  public void setStrokeWidth(double width) {
    setAttributeNS(getElement(), "stroke-width", "" + width);
  }

}
